package net.lengwang.iot.middleware.utils;

import java.util.Arrays;

public class PacketUtils {

    // 将BCD码转换为时间字符串（格式：yyyy-MM-dd HH:mm:ss）
    public static String bcdToTimeString(byte[] bcdTime) {
        if (bcdTime.length != 6) {
            throw new IllegalArgumentException("BCD时间格式错误，长度应为6字节");
        }
        StringBuilder sb = new StringBuilder();
        sb.append(bcdToInt(bcdTime[0]) + 2000).append("-"); // 年份
        sb.append(bcdToInt(bcdTime[1])).append("-"); // 月份
        sb.append(bcdToInt(bcdTime[2])).append(" "); // 日期
        sb.append(bcdToInt(bcdTime[3])).append(":"); // 小时
        sb.append(bcdToInt(bcdTime[4])).append(":"); // 分钟
        sb.append(bcdToInt(bcdTime[5])); // 秒
        return sb.toString();
    }

    // 将单个字节的BCD码转换为整数
    public static int bcdToInt(byte bcdByte) {
        int high = (bcdByte & 0xF0) >> 4;
        int low = bcdByte & 0x0F;
        return high * 10 + low;
    }

    // 将整数转换为BCD码
    public static byte intToBcd(int value) {
        if (value < 0 || value > 99) {
            throw new IllegalArgumentException("数值超出BCD码表示范围");
        }
        int high = value / 10;
        int low = value % 10;
        return (byte) ((high << 4) | low);
    }

    // 计算CRC16校验，使用Modbus CRC16算法
    public static byte[] calculateCRC(byte[] data) {
        int crc = 0xFFFF; // 初始值为0xFFFF
        for (int i = 0; i < data.length; i++) {
            crc ^= (data[i] & 0xFF); // 按字节处理
            for (int j = 0; j < 8; j++) {
                if ((crc & 1) == 1) {
                    crc = (crc >> 1) ^ 0xA001; // 多项式0xA001
                } else {
                    crc >>= 1;
                }
            }
        }
        return new byte[] { (byte) (crc & 0xFF), (byte) ((crc >> 8) & 0xFF) };
    }

    // 验证CRC16校验
    public static boolean verifyCRC(byte[] data, byte[] expectedCRC) {
        byte[] calculatedCRC = calculateCRC(Arrays.copyOfRange(data, 0, data.length - 2));
        return Arrays.equals(calculatedCRC, expectedCRC);
    }

    // 将温度数据解析为浮点数（温度单位：℃，数据格式：2字节，X = MSB*256 + LSB，T = X / 100）
    public static double parseTemperature(byte[] data) {
        if (data.length != 2) {
            throw new IllegalArgumentException("温度数据长度错误，应为2字节");
        }
        int rawValue = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
        return rawValue / 100.0;
    }

    // 将湿度数据解析为浮点数（湿度单位：%，数据格式：2字节，RH = (MSB*256 + LSB) / 100）
    public static double parseHumidity(byte[] data) {
        if (data.length != 2) {
            throw new IllegalArgumentException("湿度数据长度错误，应为2字节");
        }
        int rawValue = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
        return rawValue / 100.0;
    }

    // 提取设备ID（设备ID通常是4个字节，使用16进制表示）
    public static String extractDeviceId(byte[] data) {
        if (data.length != 4) {
            throw new IllegalArgumentException("设备ID长度错误，应为4字节");
        }
        StringBuilder sb = new StringBuilder();
        for (byte b : data) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    // 将字节数组转换为十六进制字符串表示
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    // 将十六进制字符串转换为字节数组
    public static byte[] hexToBytes(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }

    /**
     * 将时间编码为BCD格式
     * @param year 年（后两位）
     * @param month 月
     * @param day 日
     * @param hour 时
     * @param minute 分
     * @param second 秒
     * @return 编码后的BCD时间字节数组
     */
    public static byte[] encodeBCDTime(int year, int month, int day, int hour, int minute, int second) {
        byte[] bcdTime = new byte[7];
        bcdTime[0] = (byte) ((year / 10 << 4) | (year % 10));
        bcdTime[1] = (byte) ((month / 10 << 4) | (month % 10));
        bcdTime[2] = (byte) ((day / 10 << 4) | (day % 10));
        bcdTime[3] = (byte) ((hour / 10 << 4) | (hour % 10));
        bcdTime[4] = (byte) ((minute / 10 << 4) | (minute % 10));
        bcdTime[5] = (byte) ((second / 10 << 4) | (second % 10));
        bcdTime[6] = 0x00; // 星期，这里设置为0
        return bcdTime;
    }
}
